package com.dc.commons.config.mvc;

import java.beans.PropertyEditorSupport;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringEscapeUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.web.PageableHandlerMethodArgumentResolver;
import org.springframework.data.web.SortHandlerMethodArgumentResolver;
import org.springframework.http.CacheControl;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.accept.ContentNegotiationManager;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.support.WebBindingInitializer;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.ContentNegotiatingViewResolver;
import org.springframework.web.servlet.view.JstlView;
import org.springframework.web.servlet.view.UrlBasedViewResolver;
import org.springframework.web.socket.config.annotation.EnableWebSocket;

import com.dc.commons.helper.DateHelper;
import com.dc.commons.interceptor.DcInterceptor;
import com.dc.commons.resolver.DcQueryHandlerMethodArgumentResolver;
import com.dc.commons.viewresolver.JsonViewResolver;
/*******************************************************************************<P>
 * 文件名: WebMvcConfig.java <br>
 * 版本: 1.0<br>
 * 描述:<br>
 * 版权所有: <br>
 * <P>
 * 创建者: 王建栋 <br>
 * 创建日期: 2015年12月17日 上午9:24:33<br>
 * 修改者: <br>
 * 修改日期: <br>
 * 修改说明: <br>
 *****************************************************************************
 */
@Configuration
@EnableWebMvc
@EnableWebSocket
@EnableAspectJAutoProxy(proxyTargetClass=true)
@ComponentScan(basePackages = "com.dc.modules", useDefaultFilters = false, 
			includeFilters = {
					@ComponentScan.Filter(type = FilterType.ANNOTATION, value = {
							Controller.class,ControllerAdvice.class})
})
@Lazy(false)
public class WebMvcConfig extends WebMvcConfigurerAdapter{
 
	/**
	 * 文件上传最大单位 M
	 * 
	 */
	@Value("${file.maxUploadSize}")
	private int maxUploadSize;
	
	/**
	 * 使用@Value需要注册该类
	 * @return PropertySourcesPlaceholderConfigurer
	 */
	@Bean  
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {  
        return new PropertySourcesPlaceholderConfigurer();  
    } 
	
	/**
	 * jsp视图
	 * @return  viewResolver
	 */
	@Bean(name="viewResolver")
    public UrlBasedViewResolver viewResolver(){
        UrlBasedViewResolver resolver = new UrlBasedViewResolver();
          resolver.setPrefix("/WEB-INF/views/modules/");
        resolver.setSuffix(".jsp");
        resolver.setViewClass(JstlView.class);
        return resolver;
    }
	
	/**
	 * 静态资源[暂时不能用，考虑后期再说]
	 */
	 @Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/statics/**")
        		.addResourceLocations("/WEB-INF/statics/")
        		.setCacheControl(CacheControl.maxAge(1L,TimeUnit.DAYS))
        		.resourceChain(true);
        		//.addResolver(new VersionResourceResolver().addFixedVersionStrategy("1.10", "/**/*.*").addContentVersionStrategy("/**"));
        
       /* registry.addResourceHandler("/resources/*")
        		.addResourceLocations("/", "classpath:/META-INF/web-resources/")
        		.setCacheControl(CacheControl.maxAge(1L,TimeUnit.DAYS));*/
        super.addResourceHandlers(registry);
    }
	 
	 /**
     * 文件上传设置
     * @return MultipartResolver
     */
    @Bean(name="multipartResolver")
    public MultipartResolver multipartResolver() {
        CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
        multipartResolver.setMaxUploadSize(1024*1024*maxUploadSize);// 10M
        return multipartResolver;
    }
    
    
    /**
     * 在此---配置ContentNegotiationManager,在无后缀名情况下默认为jsp view resolver
     */
    @Override
    public void configureContentNegotiation(
            ContentNegotiationConfigurer configurer) {
        configurer.ignoreAcceptHeader(true).defaultContentType(
                MediaType.TEXT_HTML);
    }

    /**
     *  在此---配置ContentNegotiatingViewResolver,通过此代理到不同的viewResolover
     * @param manager
     * @return ViewResolver
     */
    @Bean
    public ViewResolver contentNegotiatingViewResolver(
            ContentNegotiationManager manager) {

    	ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
        resolver.setContentNegotiationManager(manager);
        List<ViewResolver> resolvers = new ArrayList<ViewResolver>();

        resolvers.add(viewResolver());// jsp view resolver
        resolvers.add(jsonViewResolver());
       /* resolvers.add(xmlViewResolver());
        resolvers.add(pdfViewResolver());
        resolvers.add(xlsViewResolver());
        resolvers.add(xlsxViewResolver());
        resolvers.add(eventStreamViewResolver());*/

        resolver.setViewResolvers(resolvers);
        return resolver;
    }
    
    /**
     * 在此---json viewResolver
     * @return ViewResolver
     */
    @Bean
    public ViewResolver jsonViewResolver() {
        return new JsonViewResolver();
    }
    
    
    

    @Override
	public void addInterceptors(InterceptorRegistry registry) {
    	registry.addInterceptor(new DcInterceptor());
	}

	/**
     * 添加 分页解析类，参数为Pageable的时候可以根据传递的参数自动解析为对象，这里需要扩展，可以同时支持多种的表单控件
     * ##计划传递一个参数 gridType，datatable,EasyDataGrid,JqGrid 等等。
     * 在每一个组件中可以改变传递的参数，使他传递的数据统一即可。
     */
    @Override
	public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
    	// 传递排序 字段 为 sort 是一个数组， 排序字段 和排序类型 用逗号分隔
    	SortHandlerMethodArgumentResolver sort=new SortHandlerMethodArgumentResolver();
    	
    	// 分页工具 页面参数 page，每页数据 size
    	PageableHandlerMethodArgumentResolver pageable=new PageableHandlerMethodArgumentResolver(sort);
    		//分页参数 从1开始
	    pageable.setOneIndexedParameters(true);
	    pageable.setFallbackPageable(new PageRequest(0, 15));
	    
    	DcQueryHandlerMethodArgumentResolver query=new DcQueryHandlerMethodArgumentResolver(pageable);
		argumentResolvers.add(query);
	}

	@Bean
    public WebBindingInitializer webBindingInitializer(){
    	return new WebBindingInitializer(){

			@Override
			public void initBinder(WebDataBinder binder, WebRequest request) {
				
				System.out.println("requestMappingHandlerAdapter........................");
				// String类型转换，将所有传递进来的String进行HTML编码，防止XSS攻击
				binder.registerCustomEditor(String.class, new PropertyEditorSupport() {
					@Override
					public void setAsText(String text) {
						setValue(text == null ? null : StringEscapeUtils.escapeHtml4(text.trim()));
					}
					@Override
					public String getAsText() {
						Object value = getValue();
						return value != null ? value.toString() : "";
					}
				});
				// Date 类型转换
				binder.registerCustomEditor(Date.class, new PropertyEditorSupport() {
					@Override
					public void setAsText(String text) {
						Date date=DateHelper.parseDate(text);
						setValue(date);
					}
				});
			}
    		
    	};
    }

}
